package cn.lg.soar.system.biz.modules.auth.service.impl;

import cn.lg.soar.common.util.data.StringUtil;
import cn.lg.soar.core.api.IResourceApi;
import cn.lg.soar.database.base.service.impl.BaseServiceImpl;
import cn.lg.soar.system.biz.config.SystemCacheKey;
import cn.lg.soar.system.biz.modules.auth.entity.MenuPermit;
import cn.lg.soar.system.biz.modules.auth.entity.Permit;
import cn.lg.soar.system.biz.modules.auth.mapper.PermitMapper;
import cn.lg.soar.system.biz.modules.auth.service.IPermitService;
import cn.lg.soar.system.biz.modules.auth.service.MenuPermitService;
import cn.lg.soar.system.biz.modules.auth.service.RoleMenuService;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class PermitServiceImpl extends BaseServiceImpl<PermitMapper, Permit> implements IPermitService {

    protected static final Logger LOGGER = LoggerFactory.getLogger(PermitServiceImpl.class);

    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private MenuPermitService menuPermitService;
    @Autowired
    private IResourceApi resourceApi;

    @Override
    public List<Permit> listByCodes(Collection<String> codes) {
        if (CollectionUtils.isEmpty(codes)) {
            return Collections.emptyList();
        }
        codes = codes.stream().distinct().collect(Collectors.toList());
        return this.list(
                Wrappers.<Permit>lambdaQuery()
                        .select(
                                Permit::getId,
                                Permit::getCode,
                                Permit::getName
                        )
                        .in(Permit::getCode, codes)
        );
    }

    @Cacheable(value = SystemCacheKey.PERMIT_CODE_BY_ROLE, key = "#roleId")
    @Override
    public List<String> codesByRoleId(Long roleId) {

        // 获取角色关联的菜单
        List<Long> menuIds = roleMenuService.getMenuIds(roleId);
        if (CollectionUtils.isEmpty(menuIds)) {
            return Collections.emptyList();
        }
        String collect = menuIds.stream().map(Objects::toString).collect(Collectors.joining(StringUtil.COMMA));
        // 获取菜单关联的权限
        List<String> permits = listObjs(
                Wrappers.<Permit>lambdaQuery()
                        .select(Permit::getCode)
                        .exists("SELECT * FROM lg_sys_menu_2_permit WHERE lg_sys_menu_2_permit.menu_id IN("+collect+")"),
                Object::toString
        );
        // 去重
        return permits.stream().distinct().collect(Collectors.toList());
    }

    @CacheEvict(value = SystemCacheKey.PERMIT_ID_BY_MENU, allEntries = true)
    @Override
    public void clearCache() {}

    @Transactional(rollbackFor = RuntimeException.class)
    @Override
    public boolean removeByIds(Collection<?> list) {
        menuPermitService.remove(Wrappers.<MenuPermit>lambdaQuery().in(MenuPermit::getPermitId, list));
        return super.removeByIds(list);
    }

    @Override
    public Permit getByCode(String code) {
        return getOne(
                Wrappers.<Permit>lambdaQuery()
                        .eq(Permit::getCode, code)
        );
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void scanServletPathGenPermit() {
        // 查询所有接口
        Map<String, String> mappingPaths = resourceApi.getAllPath();
        // 查询现有权限
        Set<Map.Entry<String, String>> entries = mappingPaths.entrySet();
        List<Permit> list = list(
                Wrappers.<Permit>lambdaQuery()
                        .select(Permit::getCode, Permit::getId, Permit::getName)
        );
        Map<String, Permit> map = list.stream().collect(Collectors.toMap(Permit::getCode, x -> {
            x.setCode(null);
            return x;
        }));
        list.clear();
        // 分组处理
        List<Permit> insets = new ArrayList<>(mappingPaths.size());
        List<Permit> updates = new ArrayList<>(mappingPaths.size());
        for (Map.Entry<String, String> stringStringEntry : entries) {
            String code = stringStringEntry.getKey();
            String name = stringStringEntry.getValue();
            Permit permit = map.get(code);
            if (permit == null) {
                // 新增
                permit = new Permit();
                permit.setCode(code);
                permit.setName(name);
                insets.add(permit);
            }
            if (Objects.equals(name, permit.getName())) {
                continue;
            }
            // 修改
            permit.setName(name);
            updates.add(permit);
        }
        // 入库
        saveBatch(insets);
        updateBatchById(updates);
    }

}
